package util

import (
	"sync"
	"time"

	"github.com/sirupsen/logrus"
)

var workId int64 = 1
var snowflakeWorker *worker

const (
	workerBits  uint8 = 10
	numberBits  uint8 = 12
	workerMax   int64 = -1 ^ (-1 << workerBits)
	numberMax   int64 = -1 ^ (-1 << numberBits)
	timeShift   uint8 = workerBits + numberBits
	workerShift uint8 = numberBits
	startTime   int64 = 1614657081471 //2021-03-02 11:51:21 开始时间戳 毫秒 如果在程序跑了一段时间修改了epoch这个值 可能会导致生成相同的ID
)

type worker struct {
	mu        sync.Mutex
	timestamp int64
	workerId  int64
	number    int64
}

func newWorker(workerId int64) *worker {
	if workerId < 0 || workerId > workerMax {
		panic("workId 非法")
	}
	// 生成一个新节点
	return &worker{
		timestamp: 0,
		workerId:  workerId,
		number:    0,
	}
}

func (w *worker) getSnowflakeId() int64 {
	w.mu.Lock()
	defer w.mu.Unlock()
	now := time.Now().UnixNano() / 1e6
	if w.timestamp == now {
		w.number++
		if w.number > numberMax {
			for now <= w.timestamp {
				now = time.Now().UnixNano() / 1e6
			}
		}
	} else {
		w.number = 0
		w.timestamp = now
	}
	ID := int64((now-startTime)<<timeShift | (w.workerId << workerShift) | (w.number))
	return ID
}

// GetSnowflakeId 获取一个使用雪花算法得到的id
func GetSnowflakeId() int64 {
	return snowflakeWorker.getSnowflakeId()
}

func init() {
	logrus.Info("创建snowflakeWorker")
	//创建worker 全局对象
	snowflakeWorker = newWorker(workId)
}
